#include <stdio.h>
#include <stdlib.h>
#include "SuffixTree.h"
#include "Bits.h"
#include <time.h>
#include <limits.h>

int *seq; //input numeric buffer from file
int  *p; //buffer for larsson algo
unsigned int *binaryseq; //input binary from file - toattach prefixes
int sequence_len;
int binary_seq_len;

int last_suffix_to_add;

unsigned int startPositionInSequence;
char terminationCharbefore;

short prefixShift;
short prefixLength;

extern int outputBufferSize;
extern Suffix *suffixBuffer;

int create_suffix_array()
{
		  
	int n, k, l;
  
	n=sequence_len;
	if (n==0) {
	  fprintf(stderr,  "input empty\n");
	  return 0;
	}
 
	l=0;
	k=5;

	suffixsort(seq, p, n, k, l);
   
	return 0;
}

int collectOrderedSuffices(FILE *outputFile,int fileNumber)
{

	int *pi;
	int totalSuffices=0;
	int suffixCounter=0;
	int startInLongSeq, tmp, rem;
	unsigned int bitSequence,first,second;
	int nio;
	for(pi=p;pi<=p+sequence_len;++pi)
	{		
		int sufStart=(*pi);

		if( sufStart<last_suffix_to_add)
		{
			Suffix *newSuffix=&suffixBuffer[suffixCounter++];
		
			(*newSuffix).startPos=(sufStart);
			(*newSuffix).fileNumber=fileNumber;

			
			startInLongSeq=sufStart>>prefixShift; //sufStart/prefixLength=16
			tmp=(startInLongSeq<<prefixShift);
			rem=(sufStart-tmp)*2;//sufStart%prefixLength;

			if(rem==0)
			{
				(*newSuffix).bitsPrefix1=binaryseq[startInLongSeq];
				if(startInLongSeq<binary_seq_len-1)				
					(*newSuffix).bitsPrefix2=binaryseq[startInLongSeq+1];
				else
					(*newSuffix).bitsPrefix2=0;
			}
			else
			{
				bitSequence=0;
				first =binaryseq[startInLongSeq];
				first<<=rem;
				bitSequence |=first;
				if(startInLongSeq<binary_seq_len-1)
				{
					second=binaryseq[startInLongSeq+1];
					second>>=(prefixLength*2-rem);
					bitSequence |=second;
				}
				(*newSuffix).bitsPrefix1=bitSequence;
				if(startInLongSeq+1<binary_seq_len)
				{
					bitSequence=0;
					first =binaryseq[startInLongSeq+1];
					first<<=rem;
					bitSequence |=first;
					if(startInLongSeq+2<binary_seq_len)
					{
						second=binaryseq[startInLongSeq+2];
						second>>=(prefixLength*2-rem);
						bitSequence |=second;
					}
					(*newSuffix).bitsPrefix2=bitSequence;
				}
				else
					(*newSuffix).bitsPrefix2=0;
			}	
		}

		if(suffixCounter>=outputBufferSize)
		{
			//flush array
			nio = fwrite(suffixBuffer, sizeof (Suffix), suffixCounter, outputFile);
			if(nio!=suffixCounter)
			{
				printf("error writing suffix array of partition %i. Not all was written\n",fileNumber);
				exit(1);
			}			
			
			totalSuffices+=(suffixCounter);
			suffixCounter=0;
		}

	}
	
	if(suffixCounter>0)
	{
		//flush the remaining array
		nio = fwrite(suffixBuffer, sizeof (Suffix), suffixCounter, outputFile);
		if(nio!=suffixCounter)
		{
			printf("error writing suffix array. Not all was written\n");
			exit(1);
		}
		
		totalSuffices+=(suffixCounter);		
	}
	return totalSuffices;
}


int buildSuffixArrayLarsson(int *buff,int *intBuffer,unsigned int *binaryinputseq,
							 int seq_len,	int binary_seq_length, 
							 int output_len, FILE *outputFile, int fileNumber)
{	


	prefixLength=16;
	prefixShift=4; //log numBitsInLong/2

	sequence_len=seq_len;	
	last_suffix_to_add=output_len;
		
	seq=&intBuffer[0];
	p=buff;
		
	create_suffix_array();

	binaryseq=&binaryinputseq[0];


	binary_seq_len=binary_seq_length;

	if(binary_seq_length%32>0)
		binary_seq_length++;

	return collectOrderedSuffices(outputFile, fileNumber);
	
}
